﻿#pragma execution_character_set("utf-8")

#include "appkey.h"
#include "qmutex.h"
#include "qfile.h"
#include "qtimer.h"
#include "qdatetime.h"
#include "qapplication.h"
#include "qmessagebox.h"

#include <QProcess>

AppKey *AppKey::self = nullptr;
AppKey *AppKey::Instance()
{
	if (!self) {
        QMutex mutex;
        QMutexLocker locker(&mutex);
        if (!self) {
            self = new AppKey;
        }
    }

    return self;
}

AppKey::AppKey(QObject *parent) : QObject(parent)
{
    m_nDeadline = 0;
}

const QString AppKey::get_SerialNumber()
{
    QString cpu_id = "";
    QProcess p(0);
    p.start("wmic CPU get ProcessorID");
    p.waitForStarted();
    p.waitForFinished();
    cpu_id = QString::fromLocal8Bit(p.readAllStandardOutput());
    cpu_id = cpu_id.remove("ProcessorId").trimmed();

    QString lpRootPathName = "C:\\";
    LPTSTR lpVolumeNameBuffer=new TCHAR[12];//磁盘卷标
    DWORD nVolumeNameSize=12;// 卷标的字符串长度
    DWORD VolumeSerialNumber;//硬盘序列号
    DWORD MaximumComponentLength;// 最大的文件长度
    LPTSTR lpFileSystemNameBuffer=new TCHAR[10];// 存储所在盘符的分区类型的长指针变量
    DWORD nFileSystemNameSize=10;// 分区类型的长指针变量所指向的字符串长度
    DWORD FileSystemFlags;// 文件系统的一此标志
    GetVolumeInformation((LPTSTR)lpRootPathName.utf16(),
                         lpVolumeNameBuffer, nVolumeNameSize,
                         &VolumeSerialNumber, &MaximumComponentLength,
                         &FileSystemFlags,
                         lpFileSystemNameBuffer, nFileSystemNameSize);
    return (cpu_id.mid(0,4) + "D-"+ cpu_id.mid(4,4) + "R-" +
            cpu_id.mid(8,4) + "E-" + cpu_id.mid(12,4) + "A-" +
            QString::number(VolumeSerialNumber,10).mid(0,4)+"M");
}

/* 检查本地Key 是否符合标准 验证是否过期*/
int AppKey::check()
{
    //判断密钥文件是否存在,不存在则从资源文件复制出来,同时需要设置文件写权限
    QString keyName = qApp->applicationDirPath() + "/key.db";
    QFile keyFile(keyName);
    if (!keyFile.exists() || keyFile.size() == 0) {
        return -1;
    }

    //读取密钥文件
    keyFile.open(QFile::ReadOnly);
    m_sKeyData = keyFile.readLine();
    keyFile.close();

    //将从注册码文件中的密文解密
    m_sKeyData = getXorEncryptDecrypt(m_sKeyData, 110);


    QString src = m_sKeyData;
    QByteArray text = src.toLocal8Bit();
    QByteArray by = text.fromBase64(text);
    QString str = QString::fromLocal8Bit(by); // 注意：这里是处理中文用的


    QStringList data = str.split("|");

    // key文件内容错误
    if (data.count() != 4) {
        return -2;
    }

	m_sKeySerial = data.at(0);
	m_nKeySw = data.at(1).toInt();
	m_sKeyOverData = data.at(2);
	m_sKeyStartData = data.at(3);
    // 比较机械码是否一致
    QString strSerial = get_SerialNumber();
    if (m_sKeySerial.compare(strSerial)) {
        return -3;
    }

    QDateTime strKeyStar = QDateTime::fromString(m_sKeyStartData,"yyyy-MM-dd hh:mm:ss");
    QDate strKeyOver = QDate::fromString(m_sKeyOverData,"yyyy-MM-dd");
    // 看是否无期限 无期限不用比对 0 无期限  1 有期限
    if(m_nKeySw == 1){
        QDateTime dateTime;
        dateTime = QDateTime::currentDateTime();
        uint stime = dateTime.toTime_t();
        uint etime = strKeyStar.toTime_t();
        int tRet = stime - etime;

        QDate currentTime = QDate::currentDate();
        m_nDeadline = currentTime.daysTo(strKeyOver);

        // 设备过期
        if(m_nDeadline < 0){
            return -4;
        }
        if (tRet >= 0)
        {
            createKey();
        }
        else {
            return -5;
        }
    }else{
        m_nDeadline = 999;
    }
    return 0;
}

/* 生成Key*/
void AppKey::createKey()
{
    QDateTime dateTime;
    dateTime = QDateTime::currentDateTime();
    QString key = QString("%1|%2|%3|%4").arg(m_sKeySerial).arg(m_nKeySw).arg(m_sKeyOverData).arg(dateTime.toString("yyyy-MM-dd hh:mm:ss"));
    QByteArray text = key.toLocal8Bit();
    QByteArray by = text.toBase64();
    QFile file(QApplication::applicationDirPath() + "/key.db");
    file.open(QFile::WriteOnly | QIODevice::Text);
    file.write(getXorEncryptDecrypt(by, 110).toLatin1());
    file.close();
}

/* 输入密钥进行生成Key*/
int AppKey::createKey(QString keyData)
{
    QByteArray text = keyData.toLocal8Bit();
    QByteArray by = text.toBase64();
    QFile file(QApplication::applicationDirPath() + "/key.db");
    file.open(QFile::WriteOnly | QIODevice::Text);
    file.write(getXorEncryptDecrypt(by, 110).toLatin1());
    file.close();
    return 0;
}

void AppKey::createKey(QString Serial, int KeySw, QString OverData)
{
    QDateTime dateTime;
    dateTime = QDateTime::currentDateTime();
    QString key = QString("%1|%2|%3|%4").arg(Serial).arg(KeySw).arg(OverData).arg(dateTime.toString("yyyy-MM-dd hh:mm:ss"));
    QByteArray text = key.toLocal8Bit();
    QByteArray by = text.toBase64();
    QFile file(QApplication::applicationDirPath() + "/key.db");
    file.open(QFile::WriteOnly | QIODevice::Text);
    file.write(getXorEncryptDecrypt(by, 110).toLatin1());
    file.close();
}

int AppKey::getDeadline()
{
    return m_nDeadline+1;
}

void AppKey::stop()
{

}


QString AppKey::getXorEncryptDecrypt(const QString &data, char key)
{
    //采用异或加密,也可以自行更改算法
    QByteArray buffer = data.toLatin1();
    int size = buffer.size();
    for (int i = 0; i < size; i++) {
        buffer[i] = buffer.at(i) ^ key;
    }

    return QLatin1String(buffer);
}
